home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / patches / thinkc.sit / Think ƒ / scanf2.c < prev    next >
Text File  |  1989-02-25  |  13KB  |  617 lines

  1. /*
  2.     scanf routines for LightspeedC
  3.  
  4.     (C) Copyright 1986. THINK Technologies, Inc.  All rights reserved.
  5. */
  6.  
  7. #ifndef _stdioh_
  8. #include "stdio.h"
  9. #endif
  10.  
  11. #ifndef    _MacTypes_
  12. #include "MacTypes.h"
  13. #endif
  14.  
  15. #ifndef _ctypeh_
  16. #include "ctype.h"
  17. #endif
  18.  
  19. #ifndef _saneh_
  20. #include "sane.h"
  21. #endif
  22.  
  23. #ifndef _setjmph_
  24. #include "setjmp.h"
  25. #endif
  26.  
  27. #ifndef _math_
  28. #include "Math.h"
  29. #endif
  30.  
  31. #include "pascal.h"
  32.  
  33. #ifdef _MC68881_
  34.  
  35. /* conversion from 68881 to SANE extended type */
  36. static void x96tox80(x96, x80)
  37. register Extended96 *x96;
  38. register Extended80 *x80;
  39.  
  40. {
  41.     (*x80).exponent = (*x96).exponent;
  42.     (*x80).mantissa = (*x96).mantissa;
  43. }
  44.  
  45. static void x80tox96(x80, x96)
  46. register Extended80 *x80;
  47. register Extended96 *x96;
  48. {
  49.     (*x96).exponent = (*x80).exponent;
  50.     (*x96).reserved = 0;
  51.     (*x96).mantissa = (*x80).mantissa;
  52. }
  53.  
  54. #define _fromDecimal() fp68k(&_decimal_,&x80,FFEXT|FOD2B)
  55. #define _tox96() x80tox96(&x80, *(double**)argument)
  56. #else
  57.  
  58. #define _fromDecimal() fp68k(&_decimal_,*(double**)argument,FFEXT|FOD2B)
  59. #define _tox96()
  60. #endif
  61.  
  62. /*----------------------------------------------------------------------------
  63.   some global storage to prevent excessive parameter transfer
  64. ----------------------------------------------------------------------------*/
  65.  
  66. int (*_scanf_input)();        /* global pointer to function for input */
  67. int (*_scanf_putback)();    /* global pointer to function for putback */
  68. _scanf_scan();                /* function to handle formatting */
  69. jmp_buf _scanf_env;            /* for error exit context switch */
  70.  
  71. static unsigned char *destination;    /* pointer to indicate stream for output */
  72. static char scratch[256];    /* used for [ command for byte validation */
  73.  
  74. static
  75. int from_memory()
  76. {
  77.     register unsigned char c;
  78.     c = *destination;
  79.     if (c) {
  80.         destination++;
  81.         return(c);
  82.     } else return(EOF);
  83. }
  84.  
  85. static
  86. put_back_into_memory(x)
  87. char x;
  88. {
  89.     destination--;
  90. }
  91.  
  92. #line 0 sscanf
  93. int sscanf(dest, fmt)
  94. unsigned char *dest;        /* pointer to buffer space */
  95. char *fmt;                    /* pointer to format string */
  96. {
  97.     _scanf_input = from_memory;
  98.     _scanf_putback = put_back_into_memory;
  99.  
  100.     destination = dest;
  101.     return(_scanf_scan(&fmt));
  102. }
  103.  
  104. static
  105. Boolean okdigit(c, base, value_in_base_ptr)
  106. register char c;
  107. register int base;
  108. register int *value_in_base_ptr;
  109. {
  110.     /* only works for bases 2 through 10 (inclusive) and 16! */
  111.     
  112.     *value_in_base_ptr = 0;
  113.     
  114.     if (c >= '0')
  115.     {
  116.         if (c <= (((base<=10)?base:10)+'0'-1))
  117.         {
  118.             *value_in_base_ptr = c-'0';
  119.             return (true);
  120.         }
  121.         
  122.         if (base == 16)
  123.         {
  124.             /* if character is lower case, convert to upper case */
  125.             
  126.             if ((c >= 'a') && (c <= 'f')) c -= 'a'-'A';
  127.             
  128.             if ((c >= 'A') && (c <= 'F'))
  129.             {
  130.                 *value_in_base_ptr = c - 'A' + 10;
  131.                 return (true);
  132.             }
  133.         }
  134.     }
  135.     
  136.     return (false);
  137. }
  138.  
  139.  
  140. static
  141. long read_num(num,err,at_least_one, base)
  142. register unsigned num;
  143. register Boolean *err;
  144. register Boolean *at_least_one;
  145. register int base;
  146. {
  147. register long number = 0;
  148. register int c;
  149. register Boolean oneX=false;
  150. int value_in_base;
  151.  
  152.     *at_least_one = false;
  153.     *err = false;
  154.     if (num == 0) num--;
  155.     
  156.     /* if first char is EOF, then it's not a number */
  157.     
  158.     if ((c = (*_scanf_input)()) == EOF)
  159.     {
  160.         *err = true;
  161.         return(EOF);
  162.     }
  163.  
  164.     /* loop collecting digits while num is not zero */
  165.  
  166.     while (okdigit(c, base, &value_in_base) && num--)
  167.     {
  168.         number = number * base + value_in_base;
  169.         *at_least_one = true;
  170.  
  171.         /* no need to put back EOF if we hit it */
  172.         
  173.         if ((c = (*_scanf_input)()) == EOF) return (number);
  174.  
  175.         /* the form 0xNNNN is allowed for hex numbers, just swallow the
  176.             X and continue from there, but only do it once! */
  177.             
  178.         if ((base == 16) && ((c == 'x') || (c == 'X')))
  179.         {
  180.             if ((number > 0) || oneX) break;
  181.             
  182.             /* pick up next digit -- error if nothing follows X */
  183.             
  184.             if ((c = (*_scanf_input)()) == EOF) return (EOF);
  185.         }
  186.         
  187.         /* only allow hex form after first zero, otherwise it is an error */
  188.         
  189.         oneX = true;
  190.     }
  191.  
  192.     (*_scanf_putback)(c);
  193.  
  194.     return(number);
  195. }
  196.  
  197. static
  198. int skip_white()
  199. {
  200. register int c;
  201.  
  202.     do
  203.     {
  204.         if ((c = (*_scanf_input)()) == EOF) longjmp(_scanf_env, EOF);
  205.     }
  206.     while (c && isspace(c));
  207.  
  208.     return(c);    /* returns character after white space */
  209. }
  210. int _scanf_scan(fmt)
  211. char    **fmt;                  /* pointer to pointer to format string */
  212. {
  213. char    c;                    /* current character under inspection */
  214. char    *format;            /* pointer to format string */
  215. Boolean its_a_long;            /* flag to indicate long integer */
  216. Boolean its_a_short;        /* flag to indicate short integer */
  217. Boolean neg;                /* flag for negative # */
  218. register Boolean assign;    /* flag for suppression flag */
  219. Boolean    read_err;            /* Used as error flag for read_ routines */
  220. Boolean valid;                /* valid digit? */
  221. register long    value;        /* for conversion of numerics */
  222. register char    *argument;    /* pointer to arguments for fmt string */
  223. register unsigned width;    /* field width as specified by format */
  224. register int    curr_char;    /* last character read */
  225. register char    **loc;        /* used to run thru argument */
  226. int i;                        /* counter */
  227. register count;                /* counter */
  228. register int (*_scanf_putbackx)() = _scanf_putback;
  229.  
  230. #ifdef _MC68881_
  231. Extended80 x80;
  232. #endif
  233.  
  234.     if (count=setjmp(_scanf_env)) return (count); /* set up error handler */
  235.     
  236.     format = *fmt++;            /* set "format" to the format string */
  237.                                 /* "fmt" is left pointing to first argument */
  238.     argument = (char *) fmt;    /* set "argument" to point to first argument */
  239.     count = 0;                    /* set count to zero */
  240.     
  241.     while (c = *format++)        /* scan format string until NULL */
  242.     {
  243.         if (c == '%')
  244.         {
  245.             neg = false;
  246.             assign = true;
  247.  
  248.             if ((c = *format) == '*')    /* suppress mode? */
  249.             {
  250.                 assign = false;            /* set flag if so */
  251.                 format++;                /* point to next char */
  252.             }
  253.  
  254.             /* compute total field width, zero allows arbitrary width */
  255.             
  256.             width = (isdigit(*format)) ? _std_decode(&format) : 0;
  257.  
  258.             /* check if long integer is required */
  259.             
  260.             if (its_a_long = ((*format) == 'l')) format++;
  261.  
  262.             /* check if short integer is required */
  263.             
  264.             if (its_a_short = ((*format) == 'h')) format++;
  265.  
  266.             c = *format++;
  267.  
  268.             /* note that "format" is left ready for the next pass */
  269.             
  270.             switch (c)
  271.             {
  272.                  case 'd':    switch (curr_char = skip_white())
  273.                              {
  274.                                  case '+':    /* swallow a + */
  275.                                              break;
  276.                                              
  277.                                  case '-':    /* remember a -, swallow char */
  278.                                              neg = true;
  279.                                              break;
  280.                                  
  281.                                  default:    /* oops, put it back! */
  282.                                              (*_scanf_putbackx)(curr_char);
  283.                                              break;
  284.                              }
  285.  
  286.                             value = read_num(width,&read_err,&valid, 10);
  287.                             
  288.                             if (read_err) return(EOF);
  289.                                 
  290.                             if (valid == false) return(count);
  291.  
  292.                             if (neg) value = -value;
  293.                                 
  294.                             if (assign)
  295.                             {
  296.                                 if(its_a_long)
  297.                                     **(long **)argument = value;
  298.                                 else
  299.                                     **(int **)argument = value;
  300.  
  301.                                 argument += sizeof(long);
  302.                                 count++;
  303.                             }
  304.                             break;
  305.  
  306.                  case 'u':    
  307.                             (*_scanf_putbackx)(skip_white());
  308.  
  309.                             value = read_num(width,&read_err,&valid, 10);
  310.                             
  311.                             if (read_err) return(EOF);
  312.                                 
  313.                             if (valid == false) return(count);
  314.                                 
  315.                             if (assign)
  316.                             {
  317.                                 if(its_a_long)
  318.                                     **(unsigned long **)argument = value;
  319.                                 else
  320.                                     **(unsigned int **)argument = value;
  321.  
  322.                                 argument += sizeof(long);
  323.                                 count++;
  324.                             }
  325.                             break;
  326.  
  327.                  case 'x':
  328.                 case 'X':    
  329.                             (*_scanf_putbackx)(skip_white());
  330.                                 
  331.                             value = read_num(width,&read_err,&valid, 16);
  332.                             
  333.                             if (read_err) return(EOF);
  334.  
  335.                             if (valid == false) return(count);
  336.                                 
  337.                             if (assign)
  338.                             {
  339.                                 if(its_a_long)
  340.                                     **(unsigned long **)argument = value;
  341.                                 else
  342.                                     **(unsigned int **)argument = value;
  343.  
  344.                                 argument += sizeof(long);
  345.                                 count++;
  346.                             }
  347.                             break;
  348.                  case 'o':
  349.                 case 'O':    
  350.                             (*_scanf_putbackx)(skip_white());
  351.  
  352.                             value = read_num(width,&read_err,&valid, 8);
  353.                             
  354.                             if (read_err) return(EOF);
  355.  
  356.                             if (valid == false) return(count);
  357.                                 
  358.                             if (assign)
  359.                             {
  360.                                 if(its_a_long)
  361.                                     **(unsigned long **)argument = value;
  362.                                 else
  363.                                     **(unsigned int **)argument = value;
  364.  
  365.                                 argument += sizeof(long);
  366.                                 count++;
  367.                             }
  368.                             break;
  369.  
  370.                 case 'c':    if (width<=0) width = 1;
  371.                 
  372.                             loc = (char **)argument;
  373.                             
  374.                             do
  375.                             {
  376.                                 if ((curr_char = (*_scanf_input)()) == EOF)
  377.                                     return(EOF);
  378.                                     
  379.                                 if (assign)
  380.                                 {
  381.                                     **(char **)loc = curr_char;
  382.                                     (*loc)++;
  383.                                 }
  384.                                 width--;
  385.                             }
  386.                             while (width);
  387.                             
  388.                             if (assign)
  389.                             {
  390.                                 argument += sizeof(long);
  391.                                 count++;
  392.                             }
  393.  
  394.                             break;
  395.                 
  396.                 case 'p':
  397.                 case 's':    
  398.                         {    char *strStart;
  399.                             /* first char cannot be EOF after skip_white */    
  400.                             
  401.                             (*_scanf_putbackx)(skip_white());
  402.  
  403.                             loc = (char **)argument;
  404.                             strStart = *loc;
  405.  
  406.                             do
  407.                             {
  408.                                 if ((curr_char = (*_scanf_input)()) == EOF)
  409.                                 {
  410.                                     if (assign) {
  411.                                         **(char**) loc = '\0';
  412.                                         if (c == 'p') CtoPstr(strStart);
  413.                                     }
  414.                                     return (count);
  415.                                 }
  416.  
  417.                                 if (assign)
  418.                                 {
  419.                                     if (!isspace(curr_char))
  420.                                         **(char **)loc = curr_char;
  421.                                     else
  422.                                         **(char **)loc = '\0';
  423.                                     (*loc)++;
  424.                                 }
  425.                                 width--;
  426.                             }
  427.                             while ((curr_char)&&(width)&&(!isspace(curr_char)));
  428.                             if (!curr_char || isspace(curr_char))
  429.                                 (*_scanf_putbackx)(curr_char);
  430.                             else
  431.                                 if (assign)
  432.                                     **(char **)loc = '\0';
  433.  
  434.                             
  435.                             if (assign)
  436.                             {
  437.                                 argument += sizeof(long);
  438.                                 if (c == 'p') CtoPstr(strStart);
  439.                                 count++;
  440.                             }
  441.                             break;
  442.                         }
  443.  
  444.                 case '[':    neg = false;
  445.  
  446.                             if (*format == '^')        /* check for negate */
  447.                             {
  448.                                 neg = true;            /* set if necessary */
  449.                                 format++;
  450.                             }
  451.  
  452.                             loc = (char **)argument; /* point to destination */
  453.  
  454.                             /* initialize lookup table */
  455.  
  456.                             for (i=255; i>=0; i--)
  457.                                 scratch[i] = neg;    
  458.  
  459.                             /* pointing after [ or ^ */
  460.  
  461.                             while ((curr_char = *format++) != ']')
  462.                                 scratch[curr_char] = (!neg);
  463.  
  464.                             do
  465.                             {
  466.                                 if ((curr_char = (*_scanf_input)()) == EOF)
  467.                                     return(EOF);
  468.  
  469.                                 if (assign)
  470.                                 {
  471.                                     if (scratch[curr_char])
  472.                                         **(char **)loc = curr_char;
  473.                                     else
  474.                                         **(char **)loc = '\0';
  475.                                     (*loc)++;
  476.                                 }
  477.                                 width--;
  478.                             }
  479.                             while ((width) && (scratch[curr_char]));
  480.  
  481.                             if (!scratch[curr_char])
  482.                                 (*_scanf_putbackx)(curr_char);
  483.                             else
  484.                                 if (assign)
  485.                                     **(char **)loc = '\0';
  486.  
  487.                             if (assign)
  488.                             {
  489.                                 argument += sizeof(long);
  490.                                 count++;
  491.                             }
  492.                             break;
  493.  
  494.  
  495.  
  496.                 case '%':    if ((curr_char = (*_scanf_input)()) == EOF)
  497.                                 return(EOF);
  498.                             if (curr_char != '%')
  499.                                 return (count);
  500.                             break;
  501.  
  502.                 case 'f':
  503.                 case 'e':
  504.                 case 'E':
  505.                 case 'g':
  506.                 case 'G':
  507.  
  508.                         {Decimal _decimal_;
  509.                          int fblen = 0;
  510.                          
  511.                             scratch[0] = '\0';
  512.                             curr_char = skip_white();
  513.  
  514.                             valid = false;
  515.                             do
  516.                             {int index = 0;
  517.                             
  518.                                 scratch[fblen++] = curr_char;
  519.                                 scratch[fblen] = '\0';
  520.                                 read_err = false;
  521.                                 
  522.                                 if (scratch[fblen-1])
  523.                                 {
  524.                                     CStr2Dec(&scratch,&index,&_decimal_,&read_err);
  525.                                     
  526.                                     /* read_err is true if NO READ ERROR! */
  527.                                     
  528.                                     if (read_err)
  529.                                     {
  530.                                         valid = true;
  531.                                         
  532.                                         /* read next character */
  533.                                         
  534.                                         if ((curr_char = (*_scanf_input)()) == EOF) 
  535.                                             read_err = false;
  536.                                             
  537.                                         if (isspace(curr_char))
  538.                                         {
  539.                                             read_err = false;
  540.                                             (*_scanf_putbackx)(curr_char);
  541.                                         }
  542.                                     }
  543.                                     else
  544.                                         (*_scanf_putbackx)(scratch[fblen-1]);
  545.                                 }
  546.  
  547.                             } while ((read_err)&&(--width));
  548.     
  549.                             if (!valid) return(count);
  550.  
  551.                             if (assign)
  552.                             {
  553.                                 if (its_a_long) {
  554.                                     _fromDecimal();
  555.                                     _tox96();
  556.                                 }
  557.                                 else
  558.                                     if (its_a_short)
  559.                                         fp68k(&_decimal_,*(short double**)argument,FFDBL|FOD2B);
  560.                                     else
  561.                                         fp68k(&_decimal_,*(float**)argument,FFSGL|FOD2B);
  562.                                         
  563.                                 count++;
  564.                             }
  565.                             
  566.                             argument += sizeof(long);
  567.                             break;
  568.                         }
  569.             } /* end switch */
  570.         } /* end '%' */
  571.         else
  572.         {
  573.             if (!c || isspace(c))
  574.             {
  575.                 /* expecting zero or more spaces
  576.                     pdg - 6/20/86 - used to require at least 1 space! */
  577.                 
  578.                 while (isspace(curr_char = (*_scanf_input)()))
  579.                     ;
  580.                 
  581.                 /* prevent trailing white space from incurring EOF exit */
  582.                 
  583.                 if (curr_char == EOF)
  584.                 {
  585.                     if (count > 0) return (count);
  586.                     return (EOF);
  587.                 }
  588.                 
  589.                 (*_scanf_putbackx)(curr_char);
  590.  
  591.                 /* skip all contiguous spaces in format string */
  592.                 
  593.                 while (isspace(*format)) format++;
  594.             }
  595.             else
  596.             {
  597.                 if ((curr_char = (*_scanf_input)()) == EOF) return(EOF);
  598.                 
  599.                 /* character must match exactly! */
  600.                 
  601.                 if (curr_char != c)
  602.                 {
  603.                     (*_scanf_putbackx)(curr_char);
  604.                     return(count);
  605.                 }
  606.             }
  607.         } /* else % */
  608.  
  609.     } /* end while (*format) */
  610.  
  611.     /* return number of successful assignments */
  612.     
  613.     return(count);        
  614.  
  615. }
  616.  
  617.